home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / COPYPIX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-02  |  11.0 KB  |  407 lines

  1. /* $Id: copypix.c,v 3.8 1998/07/17 03:24:16 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: copypix.c,v $
  26.  * Revision 3.8  1998/07/17 03:24:16  brianp
  27.  * added Pixel.ScaleOrBiasRGBA field
  28.  *
  29.  * Revision 3.7  1998/05/31 23:50:36  brianp
  30.  * cleaned up a few Solaris compiler warnings
  31.  *
  32.  * Revision 3.6  1998/04/01 02:58:52  brianp
  33.  * applied Miklos Fazekas's 3-31-98 Macintosh changes
  34.  *
  35.  * Revision 3.5  1998/03/27 03:30:36  brianp
  36.  * fixed G++ warnings
  37.  *
  38.  * Revision 3.4  1998/02/15 01:31:41  brianp
  39.  * removed unused variables
  40.  *
  41.  * Revision 3.3  1998/02/08 20:22:14  brianp
  42.  * LOTS of clean-up and rewriting
  43.  *
  44.  * Revision 3.2  1998/02/04 00:33:45  brianp
  45.  * fixed a few cast problems for Amiga StormC compiler
  46.  *
  47.  * Revision 3.1  1998/02/01 22:16:34  brianp
  48.  * include different headers (zooming)
  49.  *
  50.  * Revision 3.0  1998/01/31 20:49:24  brianp
  51.  * initial rev
  52.  *
  53.  */
  54.  
  55.  
  56. #ifdef PC_HEADER
  57. #include "all.h"
  58. #else
  59. #include <string.h>
  60. #include "context.h"
  61. #include "copypix.h"
  62. #include "depth.h"
  63. #include "feedback.h"
  64. #include "macros.h"
  65. #include "pixel.h"
  66. #include "span.h"
  67. #include "stencil.h"
  68. #include "types.h"
  69. #include "zoom.h"
  70. #endif
  71.  
  72.  
  73.  
  74. static void copy_rgb_pixels( GLcontext* ctx,
  75.                              GLint srcx, GLint srcy, GLint width, GLint height,
  76.                              GLint destx, GLint desty )
  77. {
  78.    GLdepth zspan[MAX_WIDTH];
  79.    GLubyte rgba[MAX_WIDTH][4];
  80.    GLboolean quick_draw;
  81.    GLint sy, dy, stepy;
  82.    GLint i, j;
  83.    GLboolean setbuffer;
  84.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0F || ctx->Pixel.ZoomY!=1.0F;
  85.  
  86.    /* Determine if copy should be done bottom-to-top or top-to-bottom */
  87.    if (srcy<desty) {
  88.       /* top-down  max-to-min */
  89.       sy = srcy + height - 1;
  90.       dy = desty + height - 1;
  91.       stepy = -1;
  92.    }
  93.    else {
  94.       /* bottom-up  min-to-max */
  95.       sy = srcy;
  96.       dy = desty;
  97.       stepy = 1;
  98.    }
  99.  
  100.    if (ctx->Depth.Test) {
  101.       /* fill in array of z values */
  102.       GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
  103.       for (i=0;i<width;i++) {
  104.          zspan[i] = z;
  105.       }
  106.    }
  107.  
  108.    if (ctx->RasterMask==0 && !zoom
  109.        && destx>=0 && destx+width<=ctx->Buffer->Width) {
  110.       quick_draw = GL_TRUE;
  111.    }
  112.    else {
  113.       quick_draw = GL_FALSE;
  114.    }
  115.  
  116.    /* If read and draw buffer are different we must do buffer switching */
  117.    setbuffer = ctx->Pixel.ReadBuffer!=ctx->Color.DrawBuffer;
  118.  
  119.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  120.       if (setbuffer) {
  121.          (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  122.       }
  123.       gl_read_rgba_span( ctx, width, srcx, sy, rgba );
  124.  
  125.       if (ctx->Pixel.ScaleOrBiasRGBA) {
  126.          gl_scale_and_bias_rgba( ctx, width, rgba );
  127.       }
  128.       if (ctx->Pixel.MapColorFlag) {
  129.          gl_map_rgba( ctx, width, rgba );
  130.       }
  131.  
  132.       if (setbuffer) {
  133.          (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  134.       }
  135.       if (quick_draw && dy>=0 && dy<ctx->Buffer->Height) {
  136.          (*ctx->Driver.WriteRGBASpan)( ctx, width, destx, dy, rgba, NULL );
  137.       }
  138.       else if (zoom) {
  139.          gl_write_zoomed_rgba_span( ctx, width, destx, dy, zspan, rgba, desty);
  140.       }
  141.       else {
  142.          gl_write_rgba_span( ctx, width, destx, dy, zspan, rgba, GL_BITMAP );
  143.       }
  144.    }
  145. }
  146.  
  147.  
  148.  
  149. static void copy_ci_pixels( GLcontext* ctx,
  150.                             GLint srcx, GLint srcy, GLint width, GLint height,
  151.                             GLint destx, GLint desty )
  152. {
  153.    GLdepth zspan[MAX_WIDTH];
  154.    GLint sy, dy, stepy;
  155.    GLint i, j;
  156.    GLboolean setbuffer;
  157.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0F || ctx->Pixel.ZoomY!=1.0F;
  158.    const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
  159.  
  160.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  161.    if (srcy<desty) {
  162.       /* top-down  max-to-min */
  163.       sy = srcy + height - 1;
  164.       dy = desty + height - 1;
  165.       stepy = -1;
  166.    }
  167.    else {
  168.       /* bottom-up  min-to-max */
  169.       sy = srcy;
  170.       dy = desty;
  171.       stepy = 1;
  172.    }
  173.  
  174.    if (ctx->Depth.Test) {
  175.       /* fill in array of z values */
  176.       GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
  177.       for (i=0;i<width;i++) {
  178.          zspan[i] = z;
  179.       }
  180.    }
  181.  
  182.    /* If read and draw buffer are different we must do buffer switching */
  183.    setbuffer = ctx->Pixel.ReadBuffer!=ctx->Color.DrawBuffer;
  184.  
  185.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  186.       GLuint indexes[MAX_WIDTH];
  187.       if (setbuffer) {
  188.          (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  189.       }
  190.       gl_read_index_span( ctx, width, srcx, sy, indexes );
  191.  
  192.       if (shift_or_offset) {
  193.          gl_shift_and_offset_ci( ctx, width, indexes );
  194.       }
  195.       if (ctx->Pixel.MapColorFlag) {
  196.          gl_map_ci( ctx, width, indexes );
  197.       }
  198.  
  199.       if (setbuffer) {
  200.          (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  201.       }
  202.       if (zoom) {
  203.          gl_write_zoomed_index_span( ctx, width, destx, dy, zspan, indexes, desty );
  204.       }
  205.       else {
  206.          gl_write_index_span( ctx, width, destx, dy, zspan, indexes, GL_BITMAP );
  207.       }
  208.    }
  209. }
  210.  
  211.  
  212.  
  213. /*
  214.  * TODO: Optimize!!!!
  215.  */
  216. static void copy_depth_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
  217.                                GLint width, GLint height,
  218.                                GLint destx, GLint desty )
  219. {
  220.    GLfloat depth[MAX_WIDTH];
  221.    GLdepth zspan[MAX_WIDTH];
  222.    GLuint indexes[MAX_WIDTH];
  223.    GLubyte rgba[MAX_WIDTH][4];
  224.    GLint sy, dy, stepy;
  225.    GLint i, j;
  226.    const GLboolean zoom = ctx->Pixel.ZoomX!=1.0F || ctx->Pixel.ZoomY!=1.0F;
  227.  
  228.    if (!ctx->Buffer->Depth) {
  229.       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  230.       return;
  231.    }
  232.  
  233.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  234.    if (srcy<desty) {
  235.       /* top-down  max-to-min */
  236.       sy = srcy + height - 1;
  237.       dy = desty + height - 1;
  238.       stepy = -1;
  239.    }
  240.    else {
  241.       /* bottom-up  min-to-max */
  242.       sy = srcy;
  243.       dy = desty;
  244.       stepy = 1;
  245.    }
  246.  
  247.    /* setup colors or indexes */
  248.    if (ctx->Visual->RGBAflag) {
  249.       GLuint *rgba32 = (GLuint *) rgba;
  250.       GLuint color = *((GLuint *) ctx->Current.ByteColor);
  251.       for (i=0; i<width; i++) {
  252.          rgba32[i] = color;
  253.       }
  254.    }
  255.    else {
  256.       for (i=0;i<width;i++) {
  257.          indexes[i] = ctx->Current.Index;
  258.       }
  259.    }
  260.  
  261.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  262.       (*ctx->Driver.ReadDepthSpanFloat)( ctx, width, srcx, sy, depth );
  263.  
  264.       for (i=0;i<width;i++) {
  265.          GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
  266.          zspan[i] = (GLint) (CLAMP( d, 0.0F, 1.0F ) * DEPTH_SCALE);
  267.       }
  268.  
  269.       if (ctx->Visual->RGBAflag) {
  270.          if (zoom) {
  271.             gl_write_zoomed_rgba_span( ctx, width, destx, dy, zspan, rgba, desty );
  272.          }
  273.          else {
  274.             gl_write_rgba_span( ctx, width, destx, dy, zspan, rgba, GL_BITMAP);
  275.          }
  276.       }
  277.       else {
  278.          if (zoom) {
  279.             gl_write_zoomed_index_span( ctx, width, destx, dy,
  280.                                         zspan, indexes, desty );
  281.          }
  282.          else {
  283.             gl_write_index_span( ctx, width, destx, dy,
  284.                                  zspan, indexes, GL_BITMAP );
  285.          }
  286.       }
  287.    }
  288. }
  289.  
  290.  
  291.  
  292. static void copy_stencil_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
  293.                                  GLint width, GLint height,
  294.                                  GLint destx, GLint desty )
  295. {
  296.    GLubyte stencil[MAX_WIDTH];
  297.    GLint sy, dy, stepy;
  298.    GLint j;
  299.    const GLboolean zoom = (ctx->Pixel.ZoomX!=1.0F || ctx->Pixel.ZoomY!=1.0F);
  300.    const GLboolean shift_or_offset = ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0;
  301.  
  302.    if (!ctx->Buffer->Stencil) {
  303.       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  304.       return;
  305.    }
  306.  
  307.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  308.    if (srcy<desty) {
  309.       /* top-down  max-to-min */
  310.       sy = srcy + height - 1;
  311.       dy = desty + height - 1;
  312.       stepy = -1;
  313.    }
  314.    else {
  315.       /* bottom-up  min-to-max */
  316.       sy = srcy;
  317.       dy = desty;
  318.       stepy = 1;
  319.    }
  320.  
  321.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  322.       gl_read_stencil_span( ctx, width, srcx, sy, stencil );
  323.  
  324.       if (shift_or_offset) {
  325.          gl_shift_and_offset_stencil( ctx, width, stencil );
  326.       }
  327.       if (ctx->Pixel.MapStencilFlag) {
  328.          gl_map_stencil( ctx, width, stencil );
  329.       }
  330.  
  331.       if (zoom) {
  332.          gl_write_zoomed_stencil_span( ctx, width, destx, dy, stencil, desty );
  333.       }
  334.       else {
  335.          gl_write_stencil_span( ctx, width, destx, dy, stencil );
  336.       }
  337.    }
  338. }
  339.  
  340.  
  341.  
  342.  
  343. void gl_CopyPixels( GLcontext* ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height,
  344.             GLenum type )
  345. {
  346.    GLint destx, desty;
  347.  
  348.    if (INSIDE_BEGIN_END(ctx)) {
  349.       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  350.       return;
  351.    }
  352.  
  353.    if (width<0 || height<0) {
  354.       gl_error( ctx, GL_INVALID_VALUE, "glCopyPixels" );
  355.       return;
  356.    }
  357.  
  358.    if (ctx->NewState) {
  359.       gl_update_state(ctx);
  360.    }
  361.  
  362.    if (ctx->RenderMode==GL_RENDER) {
  363.       /* Destination of copy: */
  364.       if (!ctx->Current.RasterPosValid) {
  365.      return;
  366.       }
  367.       destx = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
  368.       desty = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
  369.  
  370.       if (type==GL_COLOR && ctx->Visual->RGBAflag) {
  371.          copy_rgb_pixels( ctx, srcx, srcy, width, height, destx, desty );
  372.       }
  373.       else if (type==GL_COLOR && !ctx->Visual->RGBAflag) {
  374.          copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
  375.       }
  376.       else if (type==GL_DEPTH) {
  377.          copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
  378.       }
  379.       else if (type==GL_STENCIL) {
  380.          copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
  381.       }
  382.       else {
  383.      gl_error( ctx, GL_INVALID_ENUM, "glCopyPixels" );
  384.       }
  385.    }
  386.    else if (ctx->RenderMode==GL_FEEDBACK) {
  387.       GLfloat color[4];
  388.       color[0] = (GLfloat) ctx->Current.ByteColor[0] / 255.0;
  389.       color[1] = (GLfloat) ctx->Current.ByteColor[1] / 255.0;
  390.       color[2] = (GLfloat) ctx->Current.ByteColor[2] / 255.0;
  391.       color[3] = (GLfloat) ctx->Current.ByteColor[3] / 255.0;
  392.       FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
  393.       gl_feedback_vertex( ctx, ctx->Current.RasterPos[0],
  394.               ctx->Current.RasterPos[1],
  395.               ctx->Current.RasterPos[2],
  396.               ctx->Current.RasterPos[3],
  397.               color, ctx->Current.Index,
  398.               ctx->Current.TexCoord );
  399.    }
  400.    else if (ctx->RenderMode==GL_SELECT) {
  401.       gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
  402.    }
  403.  
  404. }
  405.  
  406.  
  407.